package com.lncg.config;

import com.lncg.entity.BusinessPortConfig;
import com.lncg.service.IBusinessPortConfigService;
import com.lncg.service.impl.DynamicPortServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import jakarta.annotation.PreDestroy;
import java.util.List;

/**
 * Netty TCP服务器配置类
 * 
 * 负责配置和启动Netty TCP服务器，支持多端口监听。
 * 从数据库读取业务端口配置，自动启动相应端口并更新运行状态。
 * 
 * 主要功能：
 * 1. 读取数据库中的端口配置
 * 2. 启动配置的端口监听
 * 3. 更新端口运行状态到数据库
 * 4. 管理服务器生命周期
 * 
 * @author LNCG
 * @version 1.2.0
 * @since 2024-10-17
 */
@Component
public class NettyServerConfig implements CommandLineRunner {
    
    /** 日志记录器 */
    private static final Logger logger = LoggerFactory.getLogger(NettyServerConfig.class);
    
    // ==================== 配置参数 ====================
    
    /** 读空闲超时时间（秒） */
    @Value("${netty.server.idle.reader-idle:30}")
    private int readerIdleTime;
    
    /** 写空闲超时时间（秒） */
    @Value("${netty.server.idle.writer-idle:60}")
    private int writerIdleTime;
    
    /** 读写空闲超时时间（秒） */
    @Value("${netty.server.idle.all-idle:90}")
    private int allIdleTime;
    
    /** Boss线程数 */
    @Value("${netty.server.boss-threads:1}")
    private int bossThreads;
    
    /** Worker线程数 */
    @Value("${netty.server.worker-threads:16}")
    private int workerThreads;
    
    // ==================== 依赖注入 ====================
    
    /** 业务端口配置服务 */
    @Autowired
    private IBusinessPortConfigService businessPortConfigService;
    
    /** 动态端口管理服务 */
    @Autowired
    private DynamicPortServiceImpl dynamicPortService;
    
    /**
     * 启动Netty服务器
     * 
     * 使用动态端口管理服务启动所有配置的业务端口。
     * 定时任务会自动检测端口配置变化并动态调整。
     */
    public void start() {
        try {
            
            // 从数据库读取启用的业务端口配置
            List<BusinessPortConfig> businessConfigs = businessPortConfigService.getAllEnabledConfigs();
            
            // 使用动态端口管理服务启动所有配置的端口
            for (BusinessPortConfig config : businessConfigs) {
                boolean success = dynamicPortService.startPort(config.getPort());
                if (success) {
                    logger.info("Netty TCP服务器启动成功，业务端口: {} (业务: {}, 协议: {})", 
                        config.getPort(), config.getBusinessName(), config.getProtocolType());
                } else {
                    logger.error("Netty TCP服务器启动失败，业务端口: {} (业务: {}, 协议: {})", 
                        config.getPort(), config.getBusinessName(), config.getProtocolType());
                }
            }
            
            logger.info("Netty线程配置 - Boss线程数：{}，Worker线程数：{}", bossThreads, workerThreads);
            logger.info("空闲超时配置 - 读空闲：{}秒，写空闲：{}秒，读写空闲：{}秒", 
                readerIdleTime, writerIdleTime, allIdleTime);
            logger.info("总共启动 {} 个端口", dynamicPortService.getRunningPorts().size());
            logger.info("动态端口管理已启用，定时检测间隔：10秒");
            
        } catch (Exception e) {
            logger.error("Netty TCP服务器启动失败", e);
        }
    }
    
    /**
     * 停止Netty服务器
     * 
     * 使用动态端口管理服务停止所有端口并关闭Netty组件。
     */
    public void stop() {
        try {
            // 使用动态端口管理服务停止所有端口
            dynamicPortService.stopAllPorts();
            
            // 关闭Netty组件
            dynamicPortService.shutdown();
            
            logger.info("Netty TCP服务器已停止");
        } catch (Exception e) {
            logger.error("停止Netty TCP服务器失败", e);
        }
    }
    
    /**
     * Spring Boot启动完成后自动启动Netty服务器
     * 
     * 实现CommandLineRunner接口，在Spring Boot应用启动完成后自动调用。
     * 使用延迟启动确保Spring容器完全初始化。
     * 
     * @param args 命令行参数
     * @throws Exception 启动异常
     */
    @Override
    public void run(String... args) throws Exception {
        // 延迟启动，确保Spring容器完全初始化
        new Thread(() -> {
            try {
                Thread.sleep(2000); // 延迟2秒启动
                start();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.error("延迟启动Netty服务器失败", e);
            }
        }).start();
    }
    
    /**
     * Spring Boot关闭时自动停止Netty服务器
     * 
     * 使用@PreDestroy注解，在Spring容器销毁前自动调用。
     * 确保服务器能够优雅关闭。
     */
    @PreDestroy
    public void destroy() {
        stop();
    }
}
